﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using FinalYear.Helpers;

namespace FinalYear.SixtyFour
{
    public partial class FlowForm : Form
    {
        //private Capture _capture = null;
        //private Image<Gray, Byte> currentFrame = null;
        //private Image<Gray, Byte> previousFrame = null;
        private Camera[] cameras = null;
        private Parameters values = null; 
        private EfficiencyTimer timer = null;

        public FlowForm()
        {
            InitializeComponent();
            this.cameras = new Camera[2];
            values = new Parameters();
            // initialize the camera capture object and set parameters for capture.
            this.cameras[0] = new Camera();
            this.cameras[0]._capture = new Emgu.CV.Capture(0);
            this.cameras[0]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT, values.FPS);
            this.cameras[0]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, 400); // 320 x 240
            this.cameras[0]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, 400);

            this.cameras[0]._capture.Start();

            // uncomment when using another camera
            //this.cameras[1] = new Camera();
            //this.cameras[1]._capture = new Emgu.CV.Capture(1);
            //this.cameras[1]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT, 35);
            //this.cameras[1]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, 321);
            //this.cameras[1]._capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, 241);

            //this.cameras[1]._capture.Start();

            // run the obstacle detection algorithm when the application is set to idle
            Application.Idle += Application_Idle;
        }

        //private void captureButtonClick(object sender, EventArgs e)
        //{
        //    if (_capture != null)
        //    {
        //        if (_captureInProgress)
        //        {  //stop the capture
        //            btnClick.Text = "Start Capture";
        //            _capture.Pause();
        //        }
        //        else
        //        {
        //            //start the capture
        //            btnClick.Text = "Stop";
        //            _capture.Start();
        //        }

        //        _captureInProgress = !_captureInProgress;
        //    }
        //}

        private void ReleaseData()
        {
            for (int i = 0; i < cameras.Length; i++)
            {
                if (cameras[i] != null)
                    cameras[i]._capture.Dispose();
            }
        }

        private void Application_Idle(object sender, EventArgs e)
        {
            if (cameras != null)
            {
                for (int i = 0; i < cameras.Length; i++)
                {
                    if (this.cameras[i] != null)
                    {
                        //var cameraFrame = cameras[i]._capture.RetrieveBgrFrame();
                        //this.cameras[i].currentColorFrame = cameraFrame;
                        this.cameras[i].currentFrame =  cameras[i]._capture.RetrieveGrayFrame();
                        if (this.cameras[i].previousFrame != null)
                        {
                            ////Uncomment this line if you want to try out dense optical flow
                            var imageArray = this.LaunchOpticalFlow(this.cameras[i].currentFrame, this.cameras[i].previousFrame, this.cameras[i].currentColorFrame);
                           // int box = i + i % 2;
                            imgbxCurrentFrame.Image = imageArray[1].Image;
                           // imgboxEmgu[box + 1].Image = imageArray[1].Image;
                        }

                        //this.LaunchOpticalFlow();
                        this.cameras[i].previousFrame = cameras[i].currentFrame;
                    }
                }
            }
        }

        private ImageBox[] LaunchOpticalFlow(Image<Gray, byte> currentFrame, Image<Gray, byte> previousFrame, Image<Bgr,byte> currentColorFrame)
        {
            if (previousFrame != null)
            {
                this.timer = new EfficiencyTimer(Procedure.ProcessOverallFeatureDetectionAndTrack);
                ImageBox[] arrImages = ProcessFlow.ProcessLucasKanade(currentFrame, previousFrame, currentColorFrame, values);
                timer.TerminateTimer();

                this.timer = new EfficiencyTimer(Procedure.RenderImages);
                
                this.timer.TerminateTimer();
                return arrImages;
            }
            else
            {
                return null;
            }
        }

        private void FlowForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.ReleaseData();
        }

        private void trckbarFeatureCount_ValueChanged(object sender, EventArgs e)
        {
            TrackBar featureBar = (TrackBar) sender;
            this.values.NumberOfFeatures = featureBar.Value;
            int index = this.lblNumberofFeatures.Text.IndexOf(':') + 1;
            string featureString = this.lblNumberofFeatures.Text.Remove(index) + featureBar.Value;
            this.lblNumberofFeatures.Text = featureString;
        }

     
    }
}